//
////  main.m
//
//#import <Foundation/Foundation.h>
//#include <mach-o/loader.h>
//#include <mach-o/swap.h>
//#include <mach-o/fat.h>
////MARK: - 定义一些工具方法
//BOOL isFatOfMagic(uint32 magic) {
//    return magic == FAT_MAGIC || magic == FAT_CIGAM;
//}
//BOOL isMagic64(uint32 magic) {
//    return magic == MH_MAGIC_64 || magic == MH_CIGAM_64;
//}
//BOOL shouldSwapBytesOfMagic(uint32 magic) {
//    return magic == MH_CIGAM || magic == MH_CIGAM_64 || magic == FAT_CIGAM || magic == FAT_CIGAM_64;
//}
//BOOL isValidMachoOfMagic(uint32 magic){
//    return magic == FAT_MAGIC || magic == FAT_CIGAM || magic == MH_MAGIC_64 || magic == MH_CIGAM_64;
//}
//@interface NSFileHandle(Extension)
//- (NSData *)readDataFromOffSet:(unsigned long long)offset length:(NSUInteger)length;
//- (const void *)readBytesFromOffSet:(unsigned long long)offset length:(NSUInteger)length;
//@end
//
//@implementation NSFileHandle(Extension)
//- (NSData *)readDataFromOffSet:(unsigned long long)offset length:(NSUInteger)length{
//    [self seekToFileOffset:offset];
//    return [self readDataOfLength:length];
//}
//- (const void *)readBytesFromOffSet:(unsigned long long)offset length:(NSUInteger)length{
//    return [[self readDataFromOffSet:offset length:length] bytes];
//}
//@end
//
////Demo 主逻辑
//int main(int argc, const char * argv[]) {
//    NSString * machoFilePath = @"/Users/jerry/Desktop/testMacho";
//    NSFileHandle * machoFileHandle = [NSFileHandle fileHandleForReadingAtPath: machoFilePath];
//    /* 读取魔数（前4个字节）
//     要注意的是，后面还有一个魔数，是MachO部分的，此处是针对 fat_arch 和 fat_header 相关信息的。
//     后面的是用于某个arch下的 MachO 的。
//     */
//    uint32 magic = *((uint32 *)[machoFileHandle readBytesFromOffSet:0 length:4]);
//    //thin 还是 fat 版本
//    BOOL isFat = isFatOfMagic(magic);
//    //是否是64位
//    BOOL is64 = isMagic64(magic);
//    //大小端转换判断
//    BOOL shouldSwap = shouldSwapBytesOfMagic(magic);
//    
//    if(isFat){
//        int fat_header_size = sizeof(struct fat_header);
//        struct fat_header * fatHeader = (struct fat_header *)[machoFileHandle readBytesFromOffSet:0 length:fat_header_size];
//        if (shouldSwap) {
//            swap_fat_header(fatHeader, 0);
//        }
//        int arch_offset = fat_header_size;
//        uint64_t machHeaderOffset = 0;
//        //遍历所有 arch
//        for (int i = 0; i < fatHeader->nfat_arch; i++) {
//            if(is64){
//                int fat_arch_size = sizeof(struct fat_arch_64);
//                struct fat_arch_64 * arch = (struct fat_arch_64 *)[machoFileHandle readBytesFromOffSet:arch_offset length:fat_arch_size];
//                if (shouldSwap) {
//                    //大小端转换
//                    swap_fat_arch_64(arch, 1, 0);
//                }
//                //保存 mach header 的起始位置
//                machHeaderOffset = arch->offset;
//                //计算下一个 fat_arch 的起始位置
//                arch_offset += fat_arch_size;
//                NSLog(@"------ arch cpu type: %d ------", arch->cpusubtype);
//            }else{
//                int fat_arch_size = sizeof(struct fat_arch);
//                struct fat_arch * arch = (struct fat_arch *)[machoFileHandle readBytesFromOffSet:arch_offset length:fat_arch_size];
//                if (shouldSwap) {
//                    swap_fat_arch(arch, 1, 0);
//                }
//                machHeaderOffset = arch->offset;
//                arch_offset += fat_arch_size;
//                NSLog(@"------ arch cpu type: %d ------", arch->cpusubtype);
//            }
//            
//            /*------ 开始读取 mach header ------*/
//            //读取魔数(前4个字节)
//            uint32 machMagic = *((uint32 *)[machoFileHandle readBytesFromOffSet:machHeaderOffset length:4]);
//            BOOL isMach64 = isMagic64(machMagic);
//            BOOL shoudMachSwap = shouldSwapBytesOfMagic(machMagic);
//            
//            int ncmds = 0;
//            long loadCommandsOffset = 0;
//            if(isMach64){
//                int machHeaderSize = sizeof(struct mach_header_64);
//                struct mach_header_64 * header = (struct mach_header_64 *)[machoFileHandle readBytesFromOffSet:machHeaderOffset length: machHeaderSize];
//                if (shoudMachSwap) {
//                    swap_mach_header_64(header, 0);
//                }
//                //获取 load commands 的个数
//                ncmds = header -> ncmds;
//                //load commands的起始位置
//                loadCommandsOffset = machHeaderOffset + machHeaderSize;
//            }else{
//                int machHeaderSize = sizeof(struct mach_header);
//                struct mach_header * header = (struct mach_header *)[machoFileHandle readBytesFromOffSet:machHeaderOffset length: machHeaderSize];
//                if (shoudMachSwap) {
//                    swap_mach_header(header, 0);
//                }
//                
//                ncmds = header -> ncmds;
//                loadCommandsOffset = machHeaderOffset + machHeaderSize;
//            }
//            
//            /*------ 开始读取 load command ------*/
//            for (int  i = 0; i < ncmds; i++) {
//                struct load_command *cmd = (struct load_command *)[machoFileHandle readBytesFromOffSet:loadCommandsOffset length:sizeof(struct load_command)];
//                if (shoudMachSwap) {
//                    swap_load_command(cmd, 0);
//                }
//                //如果是 LC_LOAD_DYLIB类型， 则获取 dylib_command
//                if (cmd->cmd == LC_LOAD_DYLIB){
//                    struct dylib_command * dylibCmd = (struct dylib_command *)[machoFileHandle readBytesFromOffSet:loadCommandsOffset length:cmd->cmdsize];
//                    if (shoudMachSwap) {
//                        swap_dylib_command(dylibCmd, 0);
//                    }
//                    //读取 dylib_command 的 name 信息
//                    int pathstringLen = dylibCmd->cmdsize -  dylibCmd->dylib.name.offset;
//                    char * cPath = (char *)[machoFileHandle readBytesFromOffSet:loadCommandsOffset + dylibCmd->dylib.name.offset length: pathstringLen];
//                    NSString * path =  [[NSString alloc]initWithUTF8String:cPath];
//                    NSLog(@"%@", path);
//                }
//                //计算下个 load_command 的起始位置
//                loadCommandsOffset += cmd->cmdsize;
//            }
//        }
//    }else{
//        //如果是 thin 版本，就直接从上面fat版处理步骤中的 "开始读取 mach header" 开始,这里就不再重复实现了。
//        assert(false);
//    }
//    
//    return 0;
//}
